from logging import lastResort
import pymysql
import random
import time
import subprocess
import json
from selenium import webdriver
from selenium.webdriver import ActionChains, Keys
from selenium.webdriver.edge.service import Service
from selenium.webdriver.edge.options import Options
from selenium.webdriver.common.by import By
from webdriver_manager.microsoft import EdgeChromiumDriverManager
from pythonTestDouyin.DouyinAutoSendBulletChat.mysqlMethod import MysqlController
# def total(cur):
#     cur.execute("SELECT COUNT(*) FROM input_interaction")
#     total = cur.fetchone()[0]
#     return total
# def random_bullet_chat(total):
#     db_config = {
#         "host": "localhost",
#         "user": "root",
#         "passwd": "root",
#         "db": "ointment_interaction",
#         "port": 3306
#     }
#     conn = pymysql.connect(**db_config)
#     cur = conn.cursor()
#     offset = random.randrange(0, total)
#     res = cur.execute(f"SELECT comment FROM input_interaction LIMIT 1 OFFSET {offset}")
#     if res > 0:
#         # print(f"执行成功: 已执行 {res} 条数据")
#         pass
#     else:
#         print("执行失败")
#     return cur.fetchone()[0]
# def new_web():
#     # 创建option对象
#     option = Options()
#     # 保持浏览器打开状态(默认代码执行完毕浏览器关闭)
#     option.add_experimental_option("detach", True)
#     # 基本防检测设置
#     option.add_argument("--disable-blink-features=AutomationControlled")
#     # option.add_argument("--headless")
#     option.add_experimental_option("excludeSwitches", ["enable-automation"])
#     option.add_experimental_option("useAutomationExtension", False)
#     # 禁用自动化控制标志
#     option.add_argument("--disable-infobars")
#     option.add_argument("--disable-dev-shm-usage")
#     option.add_argument("--no-sandbox")
#     #用户代理
#     option.add_argument("User-Agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 Edg/118.0.2088.46")
#     # 创建webdriver对象
#     return webdriver.ChromiumEdge(service=Service('C:\CodeMake\Python\EdgeExtension\edgedriver_win64\msedgedriver.exe'), options=option)
# def new_browser(url):
#     browser = new_web()
#     #在页面加载时执行JavaScript代码
#     browser.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
#         "source": """
#         Object.defineProperty(navigator, 'webdriver', {
#           get: () => undefined
#         })
#         """
#     })
#
#     # 打开一个网页
#     browser.get(url)
#     # 浏览器最大化
#     browser.maximize_window()
#     # 元素定位隐形等待 等网页加载完成在执行定位,()内写等待最大时间,一但网页加载完毕就会立刻执行
#     browser.implicitly_wait(5)
#     # 现在网页手动登录获取cookie,在保存以之后自动登录
#     # cookies = browser.get_cookies()
#     # with open(f'cookies_1.txt', 'w') as f:
#     #     f.write(json.dumps(cookies, ensure_ascii=True))
#     # 自动登录加改变cookie保存时间
#     with open(f'cookies_1.txt', 'r') as f:
#         cookies = json.load(f)
#         new_expiry_time = int(time.time()) + 30 * 24 * 60 * 60
#     for cookie in cookies:
#         if 'expiry' in cookie:
#             cookie['expiry'] = new_expiry_time
#         browser.add_cookie(cookie)
#     with open(f'cookies_1.txt', 'w') as f:
#         f.write(json.dumps(cookies, ensure_ascii=True))
#     browser.refresh()
#     return browser
# def send(bullet_chat,browser):
#     comment = browser.find_element(By.CSS_SELECTOR, ".ace-line>span")
#     comment.send_keys(bullet_chat)
#     browser.implicitly_wait(5)
#     sleeps = round(random.uniform(0, 5), 2)
#     time.sleep(2 + sleeps)
#     commit = browser.find_element(By.CSS_SELECTOR, "#chatInput>svg")
#     print(f"发送延迟{2 + sleeps}秒")
#     commit.click()
# if __name__ == '__main__':
#     db_config={
#     "host":"localhost",
#     "user":"root",
#     "passwd":"root",
#     "db":"ointment_interaction",
#     "port":3306
#     }
#     conn = pymysql.connect(**db_config)
#     cur = conn.cursor()
#     #获取总行数 #每半小时刷新
#     total = total(cur)
#     # last_time = time.time()
#     # if time.time() - last_time > 1800:
#     #     total = total()
#     #打开哪个直播间
#     live_id = "483379663830"
#     url = f"https://live.douyin.com/{live_id}"
#     browser = new_browser(url)
#     mode = input("请选择发送模式\n1.全自动模式(每发送十条暂停)\n2.半自动模式(根据列出弹幕,选择对应弹幕发送)\n3.手动模式(自己打印输入)\n4.退出\n输入: ")
#     while mode != '4':
#         # 全自动模式 每发送十条暂停,每条间隔60-63秒,随机延迟防检测
#         if mode == '1':
#             for i in range(10):
#                 sleeps = round(random.uniform(0,3),2)
#                 time.sleep(60+sleeps)
#                 bullet_chat = random_bullet_chat(total)
#                 print(f"延迟{sleeps}秒,发送: {bullet_chat}")
#                 send(bullet_chat,browser)
#         # 半自动模式
#         if mode == '2':
#             while True:
#                 bullet_chats = []
#                 for i in range(1,11):
#                     bullet_chat = random_bullet_chat(total)
#                     bullet_chats.append(bullet_chat)
#                     print(f"{i}.{bullet_chat}")
#                 choose = input("输入发送弹幕序号(11刷新,12返回): ")
#                 if choose != "11" and choose != "12":
#                     send(bullet_chats[int(choose) - 1], browser)
#                     break
#                 if choose == "12":
#                     break
#         # 手动模式
#         if mode == '3':
#             bullet_chat = input("请输入弹幕(12返回): ")
#             if bullet_chat != "12":
#                 send(bullet_chat, browser)
#         mode = input("请选择发送模式\n1.全自动模式(每发送十条暂停)\n2.半自动模式(根据列出弹幕,选择对应弹幕发送)\n3.手动模式(自己打印输入)\n4.退出\n输入: ")
#     #提交数据
#     conn.commit()
#     #关闭游标对象,关闭连接
#     cur.close()
#     conn.close()
class DouyinBulletChatBot:
    def __init__(self, db_config,live_id):
        self.db_config = db_config
        self.conn = pymysql.connect(**db_config)
        self.cur = self.conn.cursor()
        self.live_id = live_id
        self.total_type = None
        # self.url = f"https://live.douyin.com/{self.live_id}"
        self.url = self.live_id
        self.browser = None
    @staticmethod
    def commit_db(res):
        if res > 0:
            # print(f"执行成功: 已处理 {res} 条数据")
            pass
        elif res == 0:
            print("没有数据被处理")
        else:
            print("执行失败")

    def total(self,table_name):
        self.conn = pymysql.connect(**self.db_config)
        self.cur = self.conn.cursor()
        if table_name == "input_interaction":
            self.cur.execute(f"SELECT COUNT(*) FROM {table_name} WHERE comment NOT IN (SELECT comment FROM input_ignore)")
        else :
            self.cur.execute(f"SELECT COUNT(*) FROM {table_name}")
        self.total_type = self.cur.fetchone()[0]

    @staticmethod
    def now_to_date(format_string="%Y-%m-%d %H:%M:%S"):
        time_stamp = int(time.time())
        time_array = time.localtime(time_stamp)
        str_date = time.strftime(format_string, time_array)
        return str_date

    def random_bullet_chat(self,table_name):
        self.conn = pymysql.connect(**self.db_config)
        self.cur = self.conn.cursor()
        offset = random.randrange(0, self.total_type)
        if table_name == "input_interaction":
            res = self.cur.execute(f"SELECT comment FROM {table_name} WHERE comment NOT IN (SELECT comment FROM input_ignore) LIMIT 1 OFFSET {offset}")
        else :
            res = self.cur.execute(f"SELECT comment FROM {table_name} LIMIT 1 OFFSET {offset}")
        self.commit_db(res)
        return self.cur.fetchone()[0]
    def list_bullet_chat(self,count,table_name):
            """生成指定指定数量的随机弹幕列表,并返回"""
            bullet_chats = []
            self.total(table_name)
            for i in range(1, count+1):
                bullet_chat = self.random_bullet_chat(table_name)
                bullet_chats.append(bullet_chat)
                print(f"{i}.{bullet_chat}")
            return bullet_chats
    def new_web(self):
        option = Options()
        option.debugger_address = "127.0.0.1:9225"
        # option.add_experimental_option("detach", True)
        option.add_argument("--disable-blink-features=AutomationControlled")
        # option.add_experimental_option("excludeSwitches", ["enable-automation"])
        # option.add_experimental_option("useAutomationExtension", False)
        option.add_argument("--disable-infobars")
        option.add_argument('--disable-gpu')
        option.add_argument("--disable-dev-shm-usage")
        # option.add_argument("--no-sandbox")
        # option.add_argument("User-Agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 Edg/118.0.2088.46")
        # service = Service(EdgeChromiumDriverManager().install())
        return webdriver.ChromiumEdge(service=Service('C:\CodeMake\Python\EdgeExtension\edgedriver_win64\msedgedriver.exe'), options=option)
        # return webdriver.ChromiumEdge(service=service, options=option)

    def new_browser(self):
        browser = self.new_web()
        print("EdgeDriver版本:", browser.capabilities['browserVersion'])
        browser.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
            "source": """
            Object.defineProperty(navigator, 'webdriver', {
              get: () => undefined
            })
            """
        })
        # browser.get(self.url)
        browser.maximize_window()
        browser.implicitly_wait(5)
        # with open(r'C:\My_Code\python-test\pythonTestDouyin\DouyinAutoSendBulletChat\cookies_1.txt', 'r') as f:
        #     cookies = json.load(f)
        #     new_expiry_time = int(time.time()) + 30 * 24 * 60 * 60
        # for cookie in cookies:
        #     if 'expiry' in cookie:
        #         cookie['expiry'] = new_expiry_time
        #     browser.add_cookie(cookie)
        # with open(r'C:\My_Code\python-test\pythonTestDouyin\DouyinAutoSendBulletChat\update_cookie_time.txt', 'r') as f:
        #     update_time = f.read()
        #     print(f"上次更新: {update_time}")
        #     if input("是否更新cookie(y): ") == 'y':
        #         with open(r'C:\My_Code\python-test\pythonTestDouyin\DouyinAutoSendBulletChat\cookies_1.txt', 'w') as f:
        #             f.write(json.dumps(cookies, ensure_ascii=True))
        #         with open(r'C:\My_Code\python-test\pythonTestDouyin\DouyinAutoSendBulletChat\update_cookie_time.txt', 'w') as f:
        #             f.write(self.now_to_date())
        # browser.refresh()
        return browser
    def launch_browser(self):
        """启动浏览器进程"""
        # 浏览器路径（根据您的实际安装位置调整）
        edge_path = r"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe"
        # 用户数据目录（用于保存登录状态）
        user_data_dir = r"C:\CodeMake\Python\EdgeExtension\selenium_edge"
        # 构建启动命令
        cmd = [
            edge_path,
            f"--remote-debugging-port=9225",
            f"--user-data-dir={user_data_dir}",
            self.url
        ]
        # 启动浏览器进程
        subprocess.Popen(cmd)
        print("浏览器已启动，等待 5 秒连接...")
        time.sleep(5)  # 等待浏览器完全启动
        print("浏览器已就绪")
    def start(self):
        """开启或重新开启浏览器"""
        try:
            # 尝试连接已有浏览器实例
            self.browser = self.new_browser()
            print("成功连接到现有浏览器实例")
        except Exception as e:
            print(f"连接失败: {e}，正在启动新浏览器...")
            self.launch_browser()
            self.browser = self.new_browser()
        # 确保在正确的直播间
        if self.live_id not in self.browser.current_url:
            print(self.browser.current_url)
            print(self.live_id)
            print("不在目标网址")
            # print("不在目标网址,已跳转...")
            # self.browser.get(self.url)
        self.browser.maximize_window()
        self.browser.implicitly_wait(5)
        print("浏览器准备就绪")
    @staticmethod
    def random_time(min,max):
        times = round(random.uniform(min, max), 2)
        print(f"延迟{times}秒")
        return times
    @staticmethod
    def human_type( element, text):
        """模拟人类输入速度与错误"""
        for char in text:
            element.send_keys(char)
            time.sleep(random.uniform(0.05, 0.15))
            # 随机回删
            if random.random() < 0.03:
                element.send_keys(Keys.BACKSPACE)
                time.sleep(0.1)
                element.send_keys(char)
    def send(self, bullet_chat):
        inputs = self.browser.find_element(By.ID, "chatInput")
        inputs.click()
        comment = self.browser.find_element(By.CSS_SELECTOR, ".ace-line>span")
        time.sleep(self.random_time(2, 7))
        self.human_type(comment,bullet_chat)
        self.browser.implicitly_wait(5)
        time.sleep(self.random_time(2,7))
        commit = self.browser.find_element(By.CSS_SELECTOR, "#chatInput>svg")
        commit.click()
        # 鼠标移动到指定位置（坐标）-执行
        x = random.randint(5, 20)
        y = random.randint(5, 20)
        time.sleep(self.random_time(2, 5))
        ActionChains(self.browser).move_by_offset(x, y).perform()
        self.line()
    @staticmethod
    def type_choose():
        """选择表的类型"""
        while True:
            table_name = input("请输入弹幕类型\n1.综合表\n2.好评表\n3.提问表\n输入: ")
            if table_name == "1":
                return "input_interaction"
            if table_name == "2":
                return "input_good"
            if table_name == "3":
                return "input_question"
            # if table_name == "12":
            #     return
    @staticmethod
    def mode_type():
        """选择模式"""
        return input("请选择发送模式\n1.全自动模式(每发送十条暂停)\n2.半自动模式(根据列出弹幕,选择对应弹幕发送)\n3.手动模式(自己打印输入)\n4.弹幕库操控\n5.再次开启浏览器\n6.退出\n输入: ")
    @staticmethod
    def line() :
        print("\n" +"=" * 50 +"\n")
    def run(self):
        self.line()
        mode = self.mode_type()
        while mode != '6':
            if mode == '1':
                while True:
                    self.line()
                    table_name = self.type_choose()
                    bullet_chats = self.list_bullet_chat(10,table_name)
                    choose = input("以上为将要顺序发送的弹幕请确认y(11刷新,12返回): ")
                    if choose == '11':
                        continue
                    if choose == '12':
                        break
                    # bullet_chats = ["帅!","对面不行啊","主播厉害","哈哈哈","可以","主播玩的不错","有点技术","?","哈哈哈哈","牛"]
                    min_time, max_time = input('请输间隔时间上下限(空格隔开): ').split()
                    for i in range(10):
                        time.sleep(self.random_time(int(min_time),int(max_time)))
                        print(f"发送: {bullet_chats[i]}")
                        self.send(bullet_chats[i])
            elif mode == '2':
                choose = "11"
                self.line()
                table_name = self.type_choose()
                while True:
                    if choose == "12":
                        break
                    if choose != "11":
                        self.line()
                        table_name = self.type_choose()
                    while True:
                        self.line()
                        bullet_chats = self.list_bullet_chat(10, table_name)
                        choose = input("请输入发送弹幕序号(11刷新,12返回): ")
                        if choose == "12":
                            break
                        if choose not in ("11", "12"):
                            # print(bullet_chats[int(choose) - 1])
                            self.send(bullet_chats[int(choose) - 1])
                            break
                    self.line()
                    choose = input("是否重新选择弹幕类型y(11否,12返回): ")

            elif mode == '3':
                self.line()
                bullet_chat = input("请输入弹幕(12返回): ")
                if bullet_chat != "12":
                    # print(bullet_chat)
                    self.send(bullet_chat)
            elif mode == '4':
                mysql_controller = MysqlController(db_config)
                mysql_controller.central_control()
                print("弹幕库已刷新")
            elif mode == '5':
                self.start()
            self.line()
            mode = self.mode_type()

if __name__ == '__main__':
    db_config = {
        "host": "localhost",
        "user": "root",
        "passwd": "root",
        "db": "ointment_interaction",
        "port": 3306
    }
    # live_id = input("请输入直播间ID: ")
    live_id_path = input("请输入直播间地址: ")
    bot = DouyinBulletChatBot(db_config,f"{live_id_path}")
    #开启浏览器
    bot.start()
    #开启自动弹幕服务
    try:
        bot.run()
    except Exception as e:
        print(bot.now_to_date())
        print(e)
    #结束服务
    bot.cur.close()
    bot.conn.close()
    if bot.browser:
        bot.browser.quit()